package cn.flying.cloud.flow.core.listener.event.callback;

import javax.annotation.Resource;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;

import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.event.impl.FlowableProcessCancelledEventImpl;
import org.flowable.engine.runtime.ProcessInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import cn.flying.cloud.flow.bo.FwProcInstBo;
import cn.flying.cloud.flow.core.enums.FlowStateEnum;
import cn.flying.cloud.flow.core.listener.custom.AbstractProcessCancelledHandler;
import cn.flying.cloud.flow.core.listener.entity.ProcessCancelEntity;
import cn.flying.cloud.flow.service.FwProcInstService;

/**
 * 流程取消监听
 * 执行runtimeService.deleteProcessInstance方法的时候会触发流程取消监听器回调处理
 *
 * @author: admin
 * @date: 2023年02月26日 08:26
 * @version: 1.0
 */
@Component
public class ProcessCancelledListenerCallback implements EventListenerCallback {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private RuntimeService runtimeService;
    @Resource
    private HistoryService historyService;
    @Resource
    private FwProcInstService procInstService;
    @Resource
    private ApplicationContext applicationContext;

    @Override
    public void execute(FlowableEvent event) {
        logger.info("==========流程取消监听器回调处理---start===========");
        logger.info("监听事件类型：{}", event.getType().name());
        FlowableProcessCancelledEventImpl entityEvent = (FlowableProcessCancelledEventImpl) event;
        // 流程取消（删除作废）
        runtimeService.updateBusinessStatus(entityEvent.getProcessInstanceId(), FlowStateEnum.Delete.getCode());

        // 同时修改流程状态，删除，因为工作流本身没有删除监听器，故这里要做删除操作
        FwProcInstBo inst = new FwProcInstBo();
        inst.setProcInstId(entityEvent.getProcessInstanceId());
        inst = procInstService.getOneObj(inst);
        inst.setEndTime(LocalDateTime.now());
        inst.setDuration(Duration.between(inst.getStartTime(), inst.getEndTime()).toMillis() + "");
        inst.setProcStatus(FlowStateEnum.Delete.getCode());
        inst.setRemark((String) entityEvent.getCause());
        procInstService.updateObj(inst);

        //回调自定义处理
        Map<String, AbstractProcessCancelledHandler> beans = applicationContext.getBeansOfType(AbstractProcessCancelledHandler.class);
        if (!beans.isEmpty()) {
            ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(entityEvent.getProcessInstanceId()).singleResult();
            beans.forEach((k, bean) -> {
                if (instance.getProcessDefinitionKey().equals(bean.key())) {
                    ProcessCancelEntity entity = new ProcessCancelEntity();
                    entity.setProcessInstId(instance.getProcessInstanceId());
                    entity.setProcessDefId(instance.getProcessDefinitionId());
                    entity.setProcessDefKey(instance.getProcessDefinitionKey());
                    entity.setExecutionId(entityEvent.getExecutionId());
                    entity.setBizKey(instance.getBusinessKey());
                    entity.setProcessVariables(instance.getProcessVariables());
                    entity.setTenantId(instance.getTenantId());
                    entity.setReason((String) entityEvent.getCause());
                    entity.setProcessCompleteDate(new Date());

                    bean.execute(entity);
                }
            });
        }

        logger.info("流程【{}】取消成功，实例ID：【{}】，业务流水号：【{}】", entityEvent.getProcessDefinitionId(), entityEvent.getProcessInstanceId(), inst.getBizKey());
        logger.info("==========流程取消监听器回调处理---end===========");
    }
}
